package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.admin.feign.ArticleFeign;
import com.heima.admin.feign.WemediaFeign;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.common.aliyun.GreeTextScan;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.fastdfs.FastDFSClient;
import com.heima.model.admin.dtos.NewsAuthDto;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.media.pojos.WmNews;
import com.heima.model.media.pojos.WmUser;
import com.heima.model.media.vo.WmNewsVo;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

@Service
@Log4j2
@Transactional
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {


    @Value("${fdfs.url}")
    private String fileServerUrl;

    @Autowired
    private WemediaFeign wemediaFeign;

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private AdChannelMapper adChannelMapper;

    @Autowired
    private GreeTextScan greeTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private FastDFSClient fastDFSClient;

    @Autowired
    private AdSensitiveMapper sensitiveMapper;


    @Override
    @GlobalTransactional
    public void autoScanByMediaNewsId(Integer id) {
        if (id == null) {
            log.error("当前的审核id空");
            return;
        }

        WmNews wmNews = wemediaFeign.findById(id);//查不到的！！

        //1.根据id查询自媒体文章信息
        if(null == wmNews){
            log.error("审核的自媒体文章不存在，自媒体的id:{}", id);
            return;
        }


        //2.文章状态为4（人工审核通过）直接保存数据和创建索引
        Short status = wmNews.getStatus();
        if(status!=null && status == 4){
            //保存数据
            saveAppArticle(wmNews);
            return;
        }

        //3.文章状态为8 发布时间小于等于当前时间 直接保存数据
        if(status==8 && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()){
            //保存数据
            saveAppArticle(wmNews);
            return;
        }

        //4.文章状态为1，待审核
        if(status == 1){
            //  抽取文章对象wmNews 中的中的纯文本和图片
            //  content:文章文本内容    images：图片列表
            Map<String,Object> content = extractContent(wmNews);


            //审核内容
            boolean isAudit = auditText(content.get("content").toString(),wmNews);
            if(!isAudit) return;

            //审核图片
            isAudit= auditImage((List<String>) content.get("images"),wmNews);
            if(!isAudit) return;


            // 文章内容是否包含了自管理的敏感词
            isAudit = auditSelfSensitive(content.get("content").toString(),wmNews);
            if(!isAudit) return;



            // 发布时间大于当前时间，修改文章状态为8
            if(wmNews.getPublishTime().getTime()>System.currentTimeMillis()){
                updateWmnews(wmNews,(short)8,"审核通过，待发布");
                return;
            }

            // 审核通过，保存自媒体文章，同时进行发布：修改自媒体文章状态为9
            saveAppArticle(wmNews);
        }



    }

    public static void main(String[] args) {
        String str = "发觉宋帝夫卡送的加分考生的奶粉";
        char[] chars = str.toCharArray();
        for (char aChar : chars) {
            System.out.println(aChar);
        }
    }

    //自管理敏感词过滤
    private boolean auditSelfSensitive(String content, WmNews wmNews) {
        boolean flag = true;
        if(StringUtils.isNotBlank(content)){
            List<String> list = sensitiveMapper.findAllSensitive();

            SensitiveWordUtil.initMap(list);

            Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
            if(resultMap.size()>0){
                log.error("敏感词过滤没有通过，包含了敏感词:{}", resultMap);
                updateWmnews(wmNews,(short) 2,"文章中包含了敏感词");
                flag = false;
            }
        }
        return flag;
    }

    //审核图片
    private boolean auditImage(List<String> images, WmNews wmNews) {
        boolean flag = true;

        try {
            if(images!=null && images.size()>0){
                List<byte[]> imageList = new ArrayList<>();

                for (String image : images) {//从fast中去下载每一个图片
                    if(StringUtils.isNotBlank(image)){
                        image = image.replace(fileServerUrl, "");
                        //  group1/M00/00/00/wKjIgl892wqAANwOAAJW8oQUlAc087.jpg
                        int index = image.indexOf("/");
                        String groupName = image.substring(0, index);
                        String imagePath = image.substring(index + 1);

                        byte[] download = fastDFSClient.download(groupName, imagePath);
                        imageList.add(download);
                    }
                }

                Map map = greenImageScan.imageScan(imageList);// 考虑图片的数量的限制
                if(map!= null){
                    //审核不通过
                    if(!"pass".equals(map.get("suggestion"))){
                        if("block".equals(map.get("suggestion"))){
                            //审核不通过，设置文章状态为2
                            this.updateWmnews(wmNews,(short)2,"文章中图片有违规");
                            flag = false;
                        }
                        if ("e".equals(map.get(""))){
                            //需要人工审核，设置文章状态为3
                            this.updateWmnews(wmNews,(short)3,"文章图片有不确定元素，请人工干预");
                            flag = false;
                        }
                    }
                }

            }
        }catch (Exception e){
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }


    //审核文本
    private boolean auditText(String content,WmNews wmNews) {
        boolean flag = true;//默认
        try {
            Map map = greeTextScan.greeTextScan(content);// 考虑文本长度的限制
            if(map!= null){
                //审核不通过
                if(!"pass".equals(map.get("suggestion"))){
                    if("block".equals(map.get("suggestion"))){
                        //审核不通过，设置文章状态为2
                        this.updateWmnews(wmNews,(short)2,"文章内容中有敏感词汇");
                        flag = false;
                    }
                    if ("review".equals(map.get("suggestion"))){
                        //需要人工审核，设置文章状态为3
                        this.updateWmnews(wmNews,(short)3,"文章内容中有不确定词汇，需要人工干预");
                        flag = false;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }

    private Map<String, Object> extractContent(WmNews wmNews) {

        String content = wmNews.getContent();

        StringBuilder sb = new StringBuilder();//拼接文本内容
        List<String> imagesList = new ArrayList<>();//装图片地址的集合

        // [
        // {"type":"text","value":"xxx"},
        // {"type":"text","value":"xxxx"},
        // {"type":"image","value":"图片地址"}
        // ]
        if(StringUtils.isNotBlank(content)){
            List<Map> maps = JSON.parseArray(content, Map.class);
            for (Map map : maps) {
                if(map.get("type").equals("text")){
                    sb.append(map.get("value"));
                }
                if(map.get("type").equals("image")){
                    imagesList.add(map.get("value").toString());
                }
            }
        }
        //group1/M00/00/00/wKjIgl892xmAG_yjAAB6OkkuJd4819.jpg,group1/M00/00/00/wKjIgl892xGANV6qAABzWOH8KDY775.jpg,group1/M00/00/00/wKjIgl892wKAZLhtAASZUi49De0836.jpg
        String images = wmNews.getImages();
        if(StringUtils.isNotBlank(images) && wmNews.getStatus()!=0){
            String[] split = images.split(",");
            imagesList.addAll(Arrays.asList(split));
        }

        Map<String,Object> result = new HashMap<>();
        result.put("content",sb.toString());
        result.put("images",imagesList);
        return result;
    }

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private void saveAppArticle(WmNews wmNews) {
        //保存文章
        ApArticle apArticle = saveArticle(wmNews);

        //保存app文章配置
        saveArticleConfig(apArticle);

        //保存app文章内容
        saveArticleContent(apArticle,wmNews);

        //修改自媒体文章的状态为9
        updateWmnews(wmNews,(short) 9,"审核通过，并发布");

        //TODO ES索引创建 发消息给Kafka
        //es索引创建
        Map<String,Object> map = new HashMap();
        map.put("id",apArticle.getId().toString());
        map.put("publishTime",apArticle.getPublishTime());
        map.put("layout",apArticle.getLayout());
        map.put("images",apArticle.getImages());
        map.put("authorId",apArticle.getAuthorId());
        map.put("title",apArticle.getTitle());
        map.put("content",wmNews.getContent());

        //创建文档添加到索引库中
        org.elasticsearch.action.index.IndexRequest indexRequest = new IndexRequest("app_info_article").id(apArticle.getId().toString()).source(map);
        try {
            restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void updateWmnews(WmNews wmNews, Short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wemediaFeign.updateWmNews(wmNews);
    }

    private void saveArticleContent(ApArticle apArticle,WmNews wmNews) {
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(wmNews.getContent());
        articleFeign.saveArticleContent(apArticleContent);
    }

    private void saveArticleConfig(ApArticle apArticle) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(apArticle.getId());
        apArticleConfig.setIsForward(true);
        apArticleConfig.setIsDelete(false);
        apArticleConfig.setIsDown(true);
        apArticleConfig.setIsComment(true);
        articleFeign.saveArticleConfig(apArticleConfig);
    }

    private ApArticle saveArticle(WmNews wmNews) {
        ApArticle apArticle = new ApArticle();
        apArticle.setTitle(wmNews.getTitle());//标题
        apArticle.setLayout(wmNews.getType());//布局
        apArticle.setImages(wmNews.getImages());//图片
        apArticle.setCreatedTime(new Date());//创建时间


        //文章的作者id和名称
        Integer userId = wmNews.getUserId();
        WmUser wmUser = wemediaFeign.findWmUserById(userId);
        if(wmNews!=null){
            String wmUserName = wmUser.getName();
            ApAuthor apAuthor = articleFeign.selectAuthorByName(wmUserName);
            if(apAuthor != null){
                apArticle.setAuthorId(apAuthor.getId().longValue());
                apArticle.setAuthorName(apAuthor.getName());
            }
        }

        //封装频道的信息(id 和 名称)
        Integer channelId = wmNews.getChannelId();
        AdChannel adChannel = adChannelMapper.selectById(channelId);
        if(adChannel != null){
            apArticle.setChannelId(adChannel.getId());
            apArticle.setChannelName(adChannel.getName());
        }

        return articleFeign.saveArticle(apArticle);
    }



    @Override
    public PageResponseResult findNews(NewsAuthDto dto) {
        //分页查询
        PageResponseResult responseResult =  wemediaFeign.findList(dto);
        //有图片需要显示，需要fasfdfs服务器地址
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }

    @Override
    public ResponseResult findOne(Integer id) {
        //1参数检查
        if(id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2查询数据
        WmNewsVo wmNewsVo = wemediaFeign.findWmNewsVo(id);
        //结构封装
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }

    @Override
    public ResponseResult updateStatus(Integer type, NewsAuthDto dto) {
        //1.参数检查
        if(dto == null || dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2.查询文章
        WmNews wmNews = wemediaFeign.findById(dto.getId());
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //3.审核没有通过
        if(type.equals(0)){
            updateWmnews(wmNews,(short)2,dto.getMsg());
        }else if(type.equals(1)){
            //4.人工审核通过
            updateWmnews(wmNews,(short)4,"人工审核通过");
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
